package com.unidentifiable.wechat.service;

import com.alibaba.fastjson.JSON;
import com.unidentifiable.wechat.util.MessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;

/**
 * @author unidentifiable
 * @date 2021-02-28
 */
@Service("subscribeService")
@Slf4j
public class SubscribeService {
//    @Value("${subscriptionKey}")
//    public String subscriptionKey;
//    @Value("${uriBase}")
//    public String uriBase;
    @Value("${token}")
    public String token;

    /**
     * 公众号服务器校验
     *
     * @param req 请求
     * @return 校验结果
     */
    public String verification(HttpServletRequest req) {
        // 接收微信服务器发送请求时传递过来的参数
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");

        // 将token、timestamp、nonce三个参数进行字典序排序，并拼接为一个字符串
        String sortStr = sort(token, timestamp, nonce);
        // 字符串进行shal加密
        String mySignature = shal(sortStr);
        // 校验微信服务器传递过来的签名 和  加密后的字符串是否一致, 若一致则签名通过
        if (!"".equals(signature) && !"".equals(mySignature) && signature.equals(mySignature)) {
            System.out.println("-----签名校验通过-----");
            return echostr;
        } else {
            System.out.println("-----校验签名失败-----");
            return "";
        }
    }

    /**
     * 参数排序
     *
     * @param token     自定义token
     * @param timestamp timestamp
     * @param nonce     nonce
     * @return 排序后拼接字符串
     */
    public String sort(String token, String timestamp, String nonce) {
        String[] strArray = {token, timestamp, nonce};
        Arrays.sort(strArray);
        StringBuilder sb = new StringBuilder();
        for (String str : strArray) {
            sb.append(str);
        }
        return sb.toString();
    }

    /**
     * 字符串进行shal加密
     *
     * @param str 字符串
     * @return 密文
     */
    public String shal(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();

            StringBuilder hexString = new StringBuilder();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 关注请求
     *
     * @param req 请求
     * @return 关注事件结果
     */
    public String subscribeEvent(HttpServletRequest req) {
        String result = null;
        Map<String, String> map = null;

        try {
            /*
                解析请求，得到相关信息
                FromUserName| openid 用户ID
                CreateTime|1614499703 时间
                MsgType|event 消息类型
                Event|subscribe 事件类型        subscribe 订阅 unsubscribe 取消订阅
                EventKey|
             */
            map = MessageUtil.parseXml(req);
            log.info(JSON.toJSONString(map));
        } catch (Exception e) {
            e.printStackTrace();
        }

        final Map<String, String> m = map;
        final String[] str = {""};

        // 新开一个线程防止当前现在延时导致微信重复发起请求
        new Thread(() -> {
            String fromUserName = m.get("FromUserName");
            log.info(fromUserName);
            String t = MessageUtil.getUserInfo(fromUserName);
            System.out.println(t);
            // 获取判断是否为关注事件
//            if (null != m && "event".equals(m.get("MsgType")) && "subscribe".equals(m.get("Event"))) {
//
//            }
        }).start();

        return result;
    }

}
